#include <stdio.h>
#include <stdlib.h>
#include <time.h> /* For time(NULL) */
#include <unistd.h> /* For getpid(), sleep */
#include <string.h> /* For initializatioj of names */



#include "subsets.h"

#define NOELS 10
#define NOSUBSETS 3

static int 
getwhich(const char *prompt,int maxchoice);

static int 
getchoice(char *args[]);

static void 
operations(Subset *s);

static void 
tests(Subset *s);

static void
print_state(void);

static
Subset s[NOSUBSETS];
char *snames[NOSUBSETS];

int 
main(void)
{
  int i;
  
  /* Initializations */
  srand(time(NULL) * getpid());

  {
    char *prefix="Subset";
    char postfix[15]; /* 15 is enough ... */
    /* unless we have a very big number of subsets ... */
    /* which is not the case */
    
    for(i=0;i<NOSUBSETS;i++)
      {
	snprintf(postfix,15,"%d",i);
	snames[i] = malloc(strlen(prefix) + strlen(postfix) + 2);
	strcpy(snames[i],prefix);
	strcat(snames[i],postfix);
      }
  }

  for(i=0;i<NOSUBSETS;i++)
    ss_empty(NOELS,s + i);


  system("clear");
  print_state();
  printf("\n");
      
  for(;;)
    {

      char *menu[]={
	"Exit",
	"Operations on subsets",
	"Tests on subsets",
	NULL
      };
      
      
      printf("Main Menu\n");
      switch(getchoice(menu))
	{
	case 0:
	   system("clear");
	  exit(EXIT_SUCCESS);
	case 1:
	  operations(s);
	  break;
	case 2:
	  tests(s);
	  break;
	default:
	  continue;
	}

      system("clear");
      print_state();
      printf("\n");
      
    }

  exit(EXIT_FAILURE);
}



void
operations(Subset *sptr)
{

  system("clear");
  print_state();
  printf("\n");
  
  for(;;)
    {
      char *args[]={
	"Done",
	"Add an element to a subset",
	"Remove an element from a subset",
	"Turn a subset into its complement",
	"Make a subset into the empty set",
	"Make a subset into the total set",
	"Set it at random",
	"Intersection of two subsets",
	"Union of two subsets",
	"Copy of a subset", 
	"Is an element in a subset",
	NULL
      };

      printf("Menu Operations on Subsets\n");      
      switch(getchoice(args))
	{
	case 0:
	  return;
	case 1:
	  {
	    int subset = getwhich("To which subset",(NOSUBSETS-1));
	    int element = getwhich("Which element",NOELS-1); 
	    
	    ss_addto(sptr + subset,element);
	  }
	  break;
	case 2:
	  {
	    int subset = getwhich("From which subset",(NOSUBSETS-1));
	    int element = getwhich("Which element",NOELS-1); 
	    
	    ss_delfrom(sptr + subset,element);
	  }
	  break;
	case 3:
	  ss_complement(
			sptr + getwhich("Which subset",(NOSUBSETS-1))
			);
	  break;
	case 4:
	  ss_empty(NOELS,
		   sptr + getwhich("Which subset",(NOSUBSETS-1)));
	  break;
	case 5:
	  ss_total(NOELS,
		   sptr + getwhich("Which subset",(NOSUBSETS-1)));
	  break;
	case 6:
	  ss_random(NOELS,
		    sptr+ getwhich("Which subset",(NOSUBSETS-1)));
	  break;
	case 7:
	  { 
	    int first,second,dest;
	    
	    first=getwhich("First subset to intersect",(NOSUBSETS-1));
	    do
	      {
		printf("Second subset to intersect"
		       " (must be different from previous)");
		second=getwhich("",(NOSUBSETS-1));
	      }
	    while(first == second);
	    do
	      {
		printf("Destination subset"
		       " (must be different from previous)");
		dest=getwhich("",(NOSUBSETS-1));
	      }
	    while(dest == first || dest == second);
	    ss_intersection(sptr + dest, sptr + first, sptr + second);
	  }
	  break;
	case 8:
	  { 
	    int first,second,dest;
	    
	    first=getwhich("First subset to make union",(NOSUBSETS-1));
	    do
	      {
		printf("Second subset to make union"
		       " (must be different from previous)");
		second=getwhich("",(NOSUBSETS-1));
	      }
	    while(first == second);
	    do
	      {
		printf("Destination subset"
		       " (must be different from previous)");
		dest=getwhich("",(NOSUBSETS-1));
	      }
	    while(dest == first || dest == second);

	    ss_union(sptr + dest, sptr + first, sptr + second);
	  }
	  break;
	case 9:
	  { 
	    int first,dest;
	    
	    first=getwhich("Subset to copy",(NOSUBSETS-1));
	    do
	      {
		printf("Destination subset"
		       " (must be different from previous)");
		dest=getwhich("",(NOSUBSETS-1));
	      }
	    while(first == dest);
	    ss_cpy(sptr + dest, sptr + first);
	  }
	  break;
	case 10:
	  { 
	    int ss,el;
	    int does_it_belongs;
	    
	    ss=getwhich("Which subset?",NOSUBSETS-1);
	    el=getwhich("Which element?",NOELS -1);
	    does_it_belongs=ss_belongs(el, sptr + ss);

	    if(does_it_belongs)
	      printf("OK\n");
	    else
	      printf("NO\n");

	    sleep(3);
	  }
	  break;
	default:
	  continue;
	}
      
      system("clear");
      print_state();
      printf("\n");
      
   }

}


void
tests(Subset *sptr)
{
  int ret = 0;
  
  system("clear");
  print_state();
  printf("\n");

  for(;;)
    {
      char *menu[]={
	"Done",
	"Equality",
	"Containment",
	NULL
      };

      printf("Menu Tests on Subsets\n");
      switch(getchoice(menu))
	{
	case 0:
	  return;
	case 1:
	  {
	    int first =  getwhich("First subset",(NOSUBSETS-1));
	    int second =  getwhich("Second subset",(NOSUBSETS-1));
	    ret = ss_equal(
			   sptr + first,
			   sptr + second
			   );
	  }
	  break;
	case 2:
	  {
	    int first =  getwhich("Smaller subset",(NOSUBSETS-1));
	    int second =  getwhich("Bigger subset",(NOSUBSETS-1));
	    ret = ss_contained(
			   sptr + first,
			   sptr + second
			   );
	  }
	  break;
	default:
	  continue;
	}

      if(ret)
	printf("Answer is yes\n");
      else
	printf("Answer is no\n");
      
      sleep(3);
      system("clear");
      print_state();
      printf("\n");
 
   }

}


void
print_state(void)
{
  int i;

  for(i=0;i<NOSUBSETS;i++)
    {
      printf("%s :\n\t",snames[i]);
      ss_print(s+i);
    }
}


int getwhich(const char *prompt,int maxchoice)
{
  int ret;

  printf("%s (0-%d) : ",prompt,maxchoice);
  fflush(stdout);

  ret = -1;
  while( ret <0 || ret > maxchoice )
    {
      scanf("%d",&ret);
      getchar();
    }

  return ret;

}

int getchoice(char *args[])
{
  int i = 0;
    
  while(args[i] != NULL)
    {
      printf("(%d) %s\n",i,args[i]);
      i++;
    }
 
  return getwhich("Enter your choice",i-1);

}
